/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package algoGenetico;

import java.lang.Integer;
import java.util.ArrayList;

/**
 *
 * @author Nathy
 */
public class OperadoresGeneticos {

    public ArrayList<Individuo> cruzamento(Individuo pai1, Individuo pai2) {
        ArrayList<Individuo> filhos = new ArrayList<Individuo>();

        Cromossomo cromPai1 = pai1.getCromossomo();
        Cromossomo cromPai2 = pai2.getCromossomo();
        int index[] = getIndexsFirstIntersection(cromPai1, cromPai2);

        //Se nao ha genes em comum com os pais::
        if (index[0] == -1) {

            if (cromPai1.getTam() == 2) {
                index[0] = 0;
            } //Ponto de corte aleatorio
            else {
                index[0] = (int) (Math.random() * (cromPai1.getTam() - 2));
            }

            if (cromPai2.getTam() == 2) {
                index[1] = 0;
            } else {
                index[1] = (int) (Math.random() * (cromPai2.getTam() - 2));
            }
        }

        Cromossomo beforeCromPai1 = new Cromossomo(getGenesBeforeIndex(cromPai1, index[0]).getGenes());
        beforeCromPai1.setGen(beforeCromPai1.getTam(), cromPai1.getGene(index[0]));
        Cromossomo afterCromPai2 = new Cromossomo(getGenesAfterIndex(cromPai2, index[1]).getGenes());
        Cromossomo cromFilho1 = new Cromossomo(concateCromossomo(beforeCromPai1, afterCromPai2).getGenes());

        Individuo filho1 = new Individuo(cromFilho1);
        filhos.add(0, filho1);

        Cromossomo beforeCromPai2 = new Cromossomo(getGenesBeforeIndex(cromPai2, index[1]).getGenes());
        beforeCromPai2.setGen(beforeCromPai2.getTam(), cromPai2.getGene(index[1]));
        Cromossomo afterCromPai1 = new Cromossomo(getGenesAfterIndex(cromPai1, index[0]).getGenes());
        Cromossomo cromFilho2 = new Cromossomo(concateCromossomo(beforeCromPai2, afterCromPai1).getGenes());

        Individuo filho2 = new Individuo(cromFilho2);
        filhos.add(1, filho2);

        return filhos;
    }

    //COM EXCESSAO DO PRIMEIRO E ULTIMO
    public int[] getIndexsFirstIntersection(Cromossomo crom1, Cromossomo crom2) {

        int index[] = {-1, -1};
        for (int cont = 1; cont < crom1.getTam() - 1; cont++) {

            for (int cont2 = 0; cont2 < crom2.getTam(); cont2++) {

                if (crom1.getGene(cont) == crom2.getGene(cont2)) {
                    index[0] = cont;
                    index[1] = cont2;
                    return index;
                }
            }
        }
        return index;
    }

    public Cromossomo concateCromossomo(Cromossomo crom1, Cromossomo crom2) {
        Cromossomo cromResult = new Cromossomo(crom1.getGenes());

        for (int cont = 0; cont < crom2.getTam(); cont++) {
            cromResult.setGen(crom1.getTam() + cont, crom2.getGene(cont));
        }
        return cromResult;
    }

    public Cromossomo getGenesBeforeIndex(Cromossomo crom1, int index) {
        Cromossomo cromResult = new Cromossomo(crom1.getGenes());
        for (int cont = index; cont < crom1.getTam(); cont++) {
            cromResult.removeGen(index);
        }
        return cromResult;
    }

    public Cromossomo getGenesAfterIndex(Cromossomo crom1, int index) {
        Cromossomo cromResult = new Cromossomo(crom1.getGenes());
        for (int cont = 0; cont <= index; cont++) {
            cromResult.removeGen(0);
        }
        return cromResult;
    }

    public Individuo mutacaoPorInsercao(Cromossomo cromOld, int quantPontos) {
        Cromossomo cromNew = new Cromossomo(cromOld.getGenes());
        int origem = cromNew.removeGen(0);
        int destino = cromNew.removeGen(cromNew.getTam() - 1);

        //int origem = cromNew.getGene(0);

        if (cromNew.getTam() <= 1) {
//            System.out.println("==> cromNew.getTam() " + cromNew.getGenes().size());
            cromNew.setGen(0,(int) (Math.random() * (quantPontos)));
            cromNew.setGen(0,(int) (Math.random() * (quantPontos)));
//            System.out.println("cromNew.getTam() " + cromNew.getGenes().size() + "\n cromNew.getGenes() "+cromNew.getGenes().get(0));
        }

        if (cromNew.getTam() > 1) {
            int index = -1;
            int index2 = -1;
//            do{
            index = (int) (Math.random() * (cromNew.getTam()));
//            System.out.println("index 1 eh " + index);
//            }while(index==0);

            int genRemovido = cromNew.getGene(index);
            do {
                index2 = (int) (Math.random() * (cromNew.getTam()));

            } while (index2 == index);
//            System.out.println("index 2 eh " + index2);
            cromNew.removeGen(index);
            cromNew.setGen(index2, genRemovido);

        } /*Neste caso, adiciono um gene aleatoriamente dentre os possiveis*/ //else {
//            int index = 0;
//            do {
//                index = (int) (Math.random() * (quantPontos));
//            } while (index == origem || index == destino);
//            cromNew.setGen(cromNew.getTam(), index);
//        }

        cromNew.setGen(0, origem);
        cromNew.setGen(cromNew.getTam(), destino);
        return new Individuo(new Cromossomo(cromNew.getGenes()));
    }
}
